package utils;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import lombok.Data;
import lombok.SneakyThrows;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: gcr
 * @Date: 2022-5-30 17:05
 */
public class Utils {

    // 获取现在年，方法是当前时间戳减去8个月后再取年，即2021年7月1日是2021年，2021年6月1日是2020年。此用于新词发现，最长的比较就是一年半与之前的所有相比。
    public static Integer getNowYear() {
        long time = System.currentTimeMillis() - 60 * 60 * 24 * 30 * 6 * 1000L;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String format = sdf.format(new Date(time));
        if (NumberUtil.isInteger(format)) {
            return Integer.parseInt(format);
        }
        return 1900;
    }


    @SneakyThrows
    /**
     * 带有多线程确定线程数进行
     * 表必须是id 主键
     * tableName 表名
     * use 数据操作对象
     * tableName thread 线程数
     */
    public static List<Entity> getAllDbInfo(String tableName, Db use, int thread, String colum) {
        List<Entity> res = Collections.synchronizedList(new ArrayList<>());
        String col = "id";
        if (colum.length() > 0) {
            col = colum;
        }
        Entity entity = use.queryOne("select count(1) as cou from " + tableName);
        if (entity != null) {
            Integer cou = entity.getInt("cou");
            if (cou > 10000) {
                // 进行分页查询
                SmallTool.printMess("数量大于1万分页查询");
                //+++++++++++++++++++++++++++++++++++++++++++++
                int onePageNum = 10000;
                int from = 1;
                int max = 0;
                List<Entity> tableNum = use.query("select count(1) as count from " + tableName);
                int count = tableNum.get(0).getInt("count");
                if (count > 0) {
                    max = use.queryNumber("select max( " + col + " ) from " + tableName).intValue();
                }
                int page = max / onePageNum;
                if (max % onePageNum != 0) {
                    page++;
                }
                List<PageInfo> pageInfos = new ArrayList<>();
                for (int i = 1; i <= page; i++) {
                    int start = (i - 1) * onePageNum + from;
                    int stop = i * onePageNum + from - 1;
                    if (stop > max) {
                        stop = max + onePageNum;
                    }
                    pageInfos.add(new PageInfo(start, stop));
                }
                List<Entity> finalRes = Collections.synchronizedList(new ArrayList<>(10000000));
                ExecutorService excutor = Executors.newFixedThreadPool(thread);
                final CountDownLatch countDownLatch = new CountDownLatch(pageInfos.size());
                for (PageInfo pageInfo : pageInfos) {
                    excutor.execute(new Task(pageInfo, tableName, col, use, finalRes, countDownLatch, page));
                }
                try {
                    countDownLatch.await();
                } catch (Exception e) {
                } finally {
                    excutor.shutdown();
                }
                res = finalRes;
                //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            } else {
                res = use.query("select * from " + tableName);
            }
            if (res != null && res.size() == cou) {
                SmallTool.printMess("数量一致 返回++++++++++++");
            } else {
                SmallTool.printMessError("数量不一致 返回++++++++++++");

            }
        }
        return res;
    }


    @SneakyThrows
    /**
     * 带有多线程确定线程数进行
     * id 主键id名字
     * tableName 表名
     * use 数据操作对象
     * tableName thread 线程数
     */
    public static List<Entity> getAllDbInfoByPriID(String id, String tableName, Db use, int thread) {
        List<Entity> res = Collections.synchronizedList(new ArrayList<>());
        Entity entity = use.queryOne("select count(1) as cou from " + tableName);
        if (entity != null) {
            Integer cou = entity.getInt("cou");
            if (cou > 10000) {
                // 进行分页查询
                SmallTool.printMess("数量大于1万分页查询");
                //+++++++++++++++++++++++++++++++++++++++++++++
                int onePageNum = 10000;
                int from = 1;
                int max = 0;
                List<Entity> tableNum = use.query("select count(1) as count from " + tableName);
                int count = tableNum.get(0).getInt("count");
                if (count > 0) {
                    max = use.queryNumber("select max(" + id + ") from " + tableName).intValue();
                }
                int page = max / onePageNum;
                if (max % onePageNum != 0) {
                    page++;
                }
                List<PageInfo> pageInfos = new ArrayList<>();
                for (int i = 1; i <= page; i++) {
                    int start = (i - 1) * onePageNum + from;
                    int stop = i * onePageNum + from - 1;
                    if (stop > max) {
                        stop = max + onePageNum;
                    }
                    pageInfos.add(new PageInfo(start, stop));
                }
                List<Entity> finalRes = Collections.synchronizedList(new ArrayList<>(10000000));
                ExecutorService excutor = Executors.newFixedThreadPool(thread);
                final CountDownLatch countDownLatch = new CountDownLatch(pageInfos.size());
                for (PageInfo pageInfo : pageInfos) {
                    excutor.execute(new Task(pageInfo, tableName, id, use, finalRes, countDownLatch, page));
                }
                try {
                    countDownLatch.await();
                } catch (Exception e) {
                } finally {
                    excutor.shutdown();
                }
                res = finalRes;
                //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            } else {
                res = use.query("select * from " + tableName);
            }
            if (res != null && res.size() == cou) {
                SmallTool.printMess("数量一致 返回++++++++++++");
            } else {
                SmallTool.printMessError("数量不一致 返回++++++++++++");

            }
        }
        return res;
    }

    static class Task implements Runnable {

        private PageInfo pageInfo;
        private Integer allSize;
        private String table;
        private String id;
        private Db use;
        private List<Entity> finalRes;
        private CountDownLatch countDownLatch;

        public Task(PageInfo pageInfo, String table, String id, Db use, List<Entity> finalRes, CountDownLatch countDownLatch, Integer allSize) {
            this.pageInfo = pageInfo;
            this.table = table;
            this.id = id;
            this.use = use;
            this.allSize = allSize;
            this.finalRes = finalRes;
            this.countDownLatch = countDownLatch;
        }

        public Task() {
        }

        @Override
        public void run() {
            try {
                List<Entity> tableData = null;

                try {
                    tableData = use.query("select * from " + table + " where " + id + "  between " + pageInfo.getFrom() + " and " + pageInfo.getTo());
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
                finalRes.addAll(tableData);
            } catch (Exception e) {
                SmallTool.printMessError("没有获取到数据++++");
            } finally {
                countDownLatch.countDown();
                SmallTool.printMess(" 现在开始： " + pageInfo.getFrom() + " -- " + pageInfo.getTo() + " 总页码数：" + allSize + "++当前页码++" + (allSize - countDownLatch.getCount()) + " 表名： " + table);

            }

        }
    }

    // 读表分页的方法
    @Data
    public static class PageInfo {
        Integer from;
        Integer to;

        public PageInfo() {
        }

        public PageInfo(Integer from, Integer to) {
            this.from = from;
            this.to = to;
        }
    }

}
